/*
* Copyright 2011 Stepan Riha
*
* This file may be used under the terms of of the
* GNU General Public License Version 3 or later (the "GPL"),
* http://www.gnu.org/licenses/gpl.html
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/


$(document).ready(function() {

	var PAGE_SIZE = 20;
	var EXTRA_PAGES = 3;
	var SERVER = 'http://bookburrito-db.appspot.com';
//	SERVER = 'http://localhost:19000';
	var SEARCH_URL = SERVER + '/library/search';
	var CONTRIBUTE_URL = SERVER + '/library/contribute';

	function filterTable() {
	
		var $search = $($(this).closest('.search')).addClass('busy');
		var searchText = $.trim($('input[type=text]', $search).val());
		
		var filter = searchText.toLowerCase().replace(/\s+/, " ");
		var tokens = filter.split(' ');
		
		$('tr', $search).each(function() {
			var $tr = $(this);
			var title = $tr.data('row').title.toLowerCase();
			
			var hide = false;
			for(var i = 0; i < tokens.length; i++) {
				if(title.indexOf(tokens[i]) < 0) {
					hide = true;
					break;
				}
			}
			
			if(hide) {
				$tr.hide();
			} else {
				$tr.show();
			}
		});
		
		$search.removeClass('busy');
		return false;
	}
	
	function showSiteInfo() {		
		var $link = $(this);
		var $td = $link.closest('td');
		var $tr = $td.closest('tr');
		var row = $tr.data('row');
		var lib = new Library(row);

		$link.remove();
		
		var $div = $('<div/>')
					.appendTo($td);
		var $a = $('<a/>')
					.text(lib.link)
					.attr('href', lib.url(lib.have));
		$a.html($a.html().replace('#{ISBN}', '<b>#{ISBN}</b>'));
		$a.appendTo($div);
		return false;
	}
	
	function setupTable(id, rows, active_rows) {
		active_rows = active_rows || {};
		var $div = $('#' + id);
		
		var $chosen_div = $('<div>').attr('id', id + '-chosen').appendTo($div);
		var $chosen_table = $('<table class="matrix"><tbody /></table>').appendTo($chosen_div);
		var $chosen_tbody = $('<tbody>').appendTo($chosen_table);
		
		var $search = $('<div class="search">').appendTo($div);
		var $search_controls = $('<div class="search_panel">')
									.appendTo($search)
									.append($('<input type="text"/>'))
									.append($('<input type="button" value="Search" />').click(filterTable));
		var $scroller = $('<div class="scroller">').appendTo($search);
		
		var $table = $('<table class="matrix"><tbody /></table>').appendTo($scroller);
		var $tbody = $('<tbody>').appendTo($table);
		for(var i = 0; i < rows.length; i++) {
			var row = rows[i];
			var id = row.id;
			var $tr = $('<tr>').data('row', row);
			var $label = $('<label>').attr('for', id).text(" " + row.title);
			var $check = $('<input type="checkbox">')
							.attr('id', id)
							.prependTo($label);
			$check.data('row', row);
			var active = row.active() || active_rows[row.name];
			if(active) {
				$check.attr('checked', 'checked');
			}
			var $td = $('<td>').append($label).appendTo($tr);
			if(active) {
				$tr.appendTo($chosen_tbody);
			} else {
				$tr.appendTo($tbody);
			}
		}
		
		$tbody.delegate('input', 'click', function() {
			var $this = $(this);
			var $tr = $this.closest('tr');
			var title = $tr.data('row').title;
			var name = $tr.data('row').name;
			
			$tr.appendTo($chosen_tbody);

			$($('tr', $chosen_tbody).get().reverse()).each(function() {
				var row = $(this).data('row');
				if(row.title > title
					|| (row.title == title && row.name > name)) {
					$tr.insertBefore($(this));
				}
			});
			
			$($tr).effect("highlight", { color: "#99ff66" }, 2000);
		});
		
	}
	
	function ajaxFetchData($div, search, kind, offset) {
		
		$div.addClass('busy');
		jQuery.ajax({

			url: SEARCH_URL,
			
			data: {
				q: search,
				kind: kind,
				offset: offset,
				limit: PAGE_SIZE
			},

			success: function(data, textStatus, jqXHR) {
				updateAjaxTable($div, $.parseJSON(jqXHR.responseText));
				$div.removeClass('busy');
			},

			error: function(jqXHR, textStatus, errorThrown) {
				$div.removeClass('busy');
			}
		});
	}

	function pageLink($div, results, page, title) {
		var offset = (page - 1) * PAGE_SIZE;
		return $('<a href="#"/>')
			.html(title || page)
			.attr('title', (offset + 1) + "...")
			.data('offset', offset)
			.click(function() {
				ajaxFetchData($div, results.query, results.kind, $(this).data('offset'));
				return false;
			});
	}
	
	function buildPager($div, results) {
		var pages = Math.floor((results.count + PAGE_SIZE - 1) / PAGE_SIZE);
		
		if(pages <= 1) {
			return '';
		}
		
		var $pager = $('<div class="pager"/>');
		var current_page = results.offset / PAGE_SIZE + 1;
		var firstPage = 1;
		var lastPage = pages;
		
		if(pages > 2*EXTRA_PAGES+1) {
			if(current_page > lastPage - EXTRA_PAGES) {
				firstPage = lastPage - 2*EXTRA_PAGES+1;
			} else if(current_page < EXTRA_PAGES + 1) {
				lastPage = 2*EXTRA_PAGES;
			} else {
				firstPage = current_page - EXTRA_PAGES + 1;
				lastPage = current_page + EXTRA_PAGES - 1;
				if(firstPage == 2) { firstPage = 1; }
				if(lastPage == pages - 1) { lastPage = pages; }
			}
		}
		
		// Previous
		if(current_page > 1) {
			$pager.append(pageLink($div, results, current_page - 1, "Prev"));
		} else {
			$pager.append("Prev");
		}
		$pager.append(" | ");
		
		// First
		if(firstPage > 1) {
			$pager.append(pageLink($div, results, 1));
			$pager.append(" || ");
		}
		
		// Inner
		for(var i = firstPage; i <= lastPage; i++) {
			if(i == current_page) {
				$pager.append(i);
			} else {
				$pager.append(pageLink($div, results, i));
			}
			if(i < lastPage) {
				$pager.append(" | ");
			}
		}

		// Last
		if(lastPage < pages) {
			$pager.append(" || ");
			$pager.append(pageLink($div, results, pages));
		}
		
		// Next
		$pager.append(" | ");
		if(current_page < pages) {
			$pager.append(pageLink($div, results, current_page + 1, "Next"));
		} else {
			$pager.append("Next");
		}
		
		return $pager;
	}
	
	function updateAjaxTable($div, results) {
		var libs = results.items;
		
		var chosen = {};
		$('table.chosen tbody input', $div).each(function() {
			var row = $(this).data('row');
			chosen[row.name] = row;
		});
		
		var $title = $('.search-results thead tr th', $div);
		
		$title.text("Search Results for '" + results.query + "' (" + (results.offset + 1) + " - " + (results.offset + libs.length) + " of " + results.count + ")");

		$title.append(buildPager($div, results));
		
		var $tbody = $('.search-results tbody', $div);
		$tbody.empty();
		for(var i = 0; i < libs.length; i++) {
			var row = new Library(libs[i]);
			var id = row.id;
			
			var $tr = $('<tr>').data('row', row);
			var $label = $('<label>').text(" " + row.title);
			var $info = $('<a href="#">Library Link</a>').click(showSiteInfo);
			var $check = $('<input type="checkbox">')
					.data('row', row)
					.click(chooseLibrary)
					.prependTo($label);
			if(chosen[row.name]) {
				$tr.addClass('disabled');
				$check.attr('disabled', 'disabled');
			}

			var $td = $('<td>')
				.attr('class', row.is_community ? 'community' : 'validated')
				.append($label)
				.append($info)
				.appendTo($tr);
			$tr.appendTo($tbody);
		}
	}
	
	function chooseLibrary() {
			var $this = $(this);
			var $tr = $this.closest('tr');
			var title = $tr.data('row').title;
			var name = $tr.data('row').name;
			var $div = $this.parents('div.ajax');
			var $chosen_table = $('table.chosen', $div);
			var $chosen_tbody = $('tbody', $chosen_table);
			
			$chosen_table.show();
			
			$('input', $tr).unbind('click');
			
			$tr.appendTo($chosen_tbody);
	
			$($('tr', $chosen_tbody).get().reverse()).each(function() {
				var row = $(this).data('row');
				if(row.title > title
					|| (row.title == title && row.name > name)) {
					$tr.insertBefore($(this));
				}
			});
			
			$($tr).effect("highlight", { color: "#99ff66" }, 2000);
	}
	
	function setupAjaxTable(id, active_rows) {
		active_rows = active_rows || {};
		var $div = $('#' + id);
		
		var $chosen_div = $('<div/>').attr('id', id + '-chosen').appendTo($div);
		var $chosen_table = $('<table class="matrix chosen"/>').appendTo($chosen_div);
		var $chosen_thead = $('<thead>').appendTo($chosen_table);
		
		$chosen_thead.append($("<tr><th colspan='2'>Selected Libraries</th>"));
		
		var $chosen_tbody = $('<tbody>').appendTo($chosen_table);
		
		var $search = $('<div class="search"/>').appendTo($div);
		var $searchText = $('<input type="text"/>');
		var $searchKind = $('<select/>')
			.append($('<option/>').val('').text('All'))
			.append($('<option/>').val('validated').text('BookBurrito'))
			.append($('<option/>').val('community').text('Community'));
		var $search_controls = $('<div class="search_panel">Search: </div>')
									.appendTo($search)
									.append($searchText.typeWatch({
										captureLength: 0,
										callback: function() {
											ajaxFetchData($div, $searchText.val(), $searchKind.val(), 0);
										}
									}))
									.append($searchKind.change(function() {
										ajaxFetchData($div, $searchText.val(), $searchKind.val(), 0);
									}));
		var $scroller = $('<div class="_scroller">').appendTo($search);
		
		var $table = $('<table class="matrix search-results"/>')
						.append($("<thead><tr><th colspan='2'>Search Results:</th></thead>"))
						.appendTo($scroller);
		var $tbody = $('<tbody>').appendTo($table);

		if(!active_rows.length) {
			$chosen_table.hide();
		} else {
			for(var i = 0; i < active_rows.length; i++) {
				var row = active_rows[i];
				var id = row.id;
				var $tr = $('<tr>').data('row', row);
				var $label = $('<label>').text(" " + row.title);
				var $info = $('<a href="#">Library Link</a>').click(showSiteInfo);
				var $check = $('<input type="checkbox">')
								.prependTo($label);
				$check.data('row', row);
				$check.attr('checked', 'checked');
	
				var $td = $('<td>')
					.attr('class', row.is_community ? 'community' : 'validated')
					.append($label)
					.append($info)
					.appendTo($tr);
				$tr.appendTo($chosen_tbody);
			}
		}
	}	
	
	// Stores
	setupTable('stores', BB.stores);
	
	// Libraries
	Database.getLibraries(function(activeLibs) {
		setupAjaxTable('libraries', activeLibs);
		ajaxFetchData($('#libraries'));
	});
	
	// Custom Libraries
	Database.getCustomLibraries(function(libs) {
		for(var i = 0; i < libs.length; i++) {
			addCustomRow(libs[i]);
		}
	});
	
	// Load options
	$('#worldcat').val(Prefs.getValue('worldcat', ""));
	if(Prefs.getValue('no-affiliate-codes', false)) {
		$('#no-affiliate-codes').attr('checked', 'checked');
	}
	
	// Save options
	$('#save').click(function() {
		Prefs.setValue('worldcat', $('#worldcat').val());
		Prefs.setValue('no-affiliate-codes', $('#no-affiliate-codes').is(':checked'));
		
		var libs = [];
		
		$(':checkbox').each(function() {
			var id = $(this).attr('id');
			if($(this).is(':checked')) {
				var row = $(this).data('row');
				if(row && row.kind == 'libraries') {
					libs.push(row);
				} else {
					Prefs.setValue(id, true);
				}
			} else {
				Prefs.removeValue(id);
			}
		});
		
		Database.storeAllLibraries(libs, getCustomLibraries());
		
		return false;
	});
	
	function getCustomLibraries() {
		var libs = [];
		$('#custom table.matrix tbody tr').each(function() {
			var row =$(this).data('row');
			if(row) {
				libs.push(row);
			}
		});
		return libs;
	}
	
	function addCustomRow(site, animate) {
		var $tbody = $('#custom table.matrix tbody');
		var $tr = $('<tr>').data('row', site);
		$tr.append($('<td>').text(site.title));
		var $td = $('<td class="actions">')
			.append($('<a href="#">').text('Edit').click(edit))
			.append($('<a href="#">').text('Duplicate').click(duplicate))
			.append($('<a href="#">').text('Remove').click(remove))
			.append($('<a href="#">').text('Contribute').click(share));
		$tr.append($td);			
		$tbody.append($tr);
		
		function edit() {
			var site = $(this).parents('tr').data('row');
			showCustomForm(site);
			return false;
		}
		
		function duplicate(){
			var site = $(this).parents('tr').data('row');
			showCustomForm(site, true);
			return false;
		}
		
		function remove() {
			var site = $(this).parents('tr').data('row');
			if(confirm("Remove configuration for '" + site.title + "'?"))
				removeCustomRow(site);
			return false;
		}
		
		function share() {
			var site = $(this).parents('tr').data('row');
			var $form = $('#shared-form');
			$form.empty();
			$form.attr('action', CONTRIBUTE_URL);
			var fields = ['title', 'link', 'missing', 'have', 'dont'];
			for(var i = 0; i < fields.length; i++) {
				var field = fields[i];
				var $input = $('<input/>').attr('name', field).val(site[field]);
				$form.append($input);
			}
			
			$form.submit();
			return false;
		}
		
		$('#custom-table').show();

		if(animate) {
			var title = site.title;
			var name = site.name;
			$($('tr', $tbody).get().reverse()).each(function() {
				var row = $(this).data('row');
				if(row.title > title
					|| (row.title == title && row.name > name)) {
					$tr.insertBefore($(this));
				}
			});
			
			$($tr).effect("highlight", { color: "#99ff66" }, 2000);
		}
	};
	
	function removeCustomRow(site) {
		var visibleRows = 0;
		$('#custom table.matrix tbody tr').each(function() {
			var $tr =$(this);
			if($tr.data('row') == site) {
				$tr.remove();
			} else {
				visibleRows++;
			}
		});
		
		if(!visibleRows) {
			$('#custom-table').hide();
		}
	};
	
	$('#add_custom').click(function(e) {
		e.stopPropagation();
		showCustomForm();
		return false;
	});
	
	$('#custom-cancel').click(function(e) {
		e.stopPropagation();
		hideCustomForm();
		return false;
	});
	
	$('#custom-match_isbn, #custom-match_missing').click(function() {
		if(matchByIsbn()) {
			$('#field-missing').hide();
		} else {
			$('#field-missing').show();
			$('#custom-missing').focus();
		}
	});
	
	$('#custom-save').click(function(e) {
		e.stopPropagation();

		var data = getCustomData();
		
		function isMatch(text, regex) {
			var result = text.match(regex);
			return (result && result.length > 0);
		}
		
		// Validate Title
		if(isMatch(data.title, /^\s*$/)) {
			alert("Lirary Title may not be blank");
			$('#custom-title').focus();
			return false;
		}
		
		// Validate Link
		if(!isMatch(data.link, /\#\{ISBN\}/)) {
			alert("Link must contain #{ISBN} token!");
			$('#custom-link').focus();
			return false;
		}
		
		// Check for duplicates
		var duplicate = null;
		$('#custom table.matrix tbody tr').each(function() {
			var row =$(this).data('row');
			if(row && row != editingSite && row.name == data.name) {
				duplicate = row;
			}
		});
		if(duplicate) {
			alert("Library name '" + data.name + "' is not unique!\n\n"
				+ "Library '" + duplicate.title + "' is named the same.");
			$('#custom-name').focus();
			return false;
		}		
		
		if(editingSite) {
			removeCustomRow(editingSite);
		}
		addCustomRow(new CustomLibrary(data), true);
		hideCustomForm();
		return false;
	});
	
	function matchByIsbn(val) {
		if(val) {
			$('#custom-match_isbn').click();
			$('#custom-match_isbn').click();
		} else if(val === false) {
			$('#custom-match_missing').click();		
			$('#custom-match_missing').click();		
		} else {
			return $('#custom-match_isbn').attr('checked');
		}
	}
	
	function customKeyUp(e) {
		  if (e.keyCode == 27) { $('#custom-cancel').click(); }   // esc
	}
	
	function hideCustomForm() {
		$(document).unbind('keyup', customKeyUp);
		$('#custom').show();
		$('#custom-form').hide();
	}
	
	var editingSite = null;
	
	function showCustomForm(site, duplicate) {
		$('#custom').hide();
		$('#custom-form .test-results').hide();
		
		if(site != null) {
			putCustomDataToControls(site);
			if(duplicate) {
				site = null;
			}
		}
		
		if(!site) {
			$('#custom-name').val(uuid());
		}
		
		editingSite = site;
		$('#custom-form').show();
		
		$(document).bind('keyup', customKeyUp);
	}

	function putCustomDataToControls(data) {
		$('#custom-form input:text').each(function(){
			var name =$(this).attr('name');
			if(data[name]) {
				$(this).val(data[name]);
			}
		});
		matchByIsbn(data.match_isbn || false);
	}
	
	function getCustomData() {
		var data = {};
		$('#custom-form input:text').each(function(){
			data[$(this).attr('name')] = $(this).val();
		});
		
		if(matchByIsbn()) {
			data.match_isbn = true;
			delete(data.missing);
		}
		
		return data;
	};

	$('#custom-test').click(function() {
		var data = getCustomData();
		
		var site = new CustomLibrary(data);
				
		var $test = $('#custom-form .test-results').text('').removeClass('succeeded').removeClass('failed').show();
		
		function trace(msg) {
			$test.html($test.html() + msg + "\n");
		}
		
		trace("Testing configuration for '" + site.title + "'...");

		var test = {
			cases: [
				{ isbn: data.have, have: true },
				{ isbn: data.dont, have: false }
			],
			error: false,
			completed: 0
		};
		
		
		function finishedTest(error) {
			test.completed++;
			if(error) {
				test.error = true;
			}

			if(test.completed == test.cases.length) {
				$test.addClass(test.error ? 'failed' : 'succeeded');
			}
		}

		
		function testIsbn(isbn, have) {
			var url = site.query_url(isbn);
			var message = have ? "Search for <b>existing</b> book" : "Search for <b>missing</b> book"
			message = "<a href='" + url + "'>" + message + "</a>";
			jQuery.ajax({
	
				url: url,
	
				success: function(data, textStatus, jqXHR) {
					var answer = site.process(jqXHR, isbn) || '';
					var found = answer == 'yes';
					var error = have != found;
					var cssClass = error ? 'error' : 'success';
					if (error) {
						message = "<span class='error'>ERROR</span>: " + message;
					} else {
						message = "<span class='success'>OK</span>: " + message;
					}
					trace(message + " returned: <span class='" + cssClass + "'>" + answer + "</span> "
					 + (found ? "(book found)" : "(book not found)"));
					finishedTest(error);
				},
	
				error: function(jqXHR, textStatus, errorThrown) {
					trace(message + " failed: " + textStatus);
					finishedTest(error);
				}
			});
		}
		
		for(var i = 0; i < test.cases.length; i++) {
			var testCase = test.cases[i];
			testIsbn(testCase.isbn, testCase.have);
		}
		
		return false;
	});
	
});
